package com.jianguozh.difs.support.api.ops;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jianguozh.difs.common.bean.R;
import com.jianguozh.difs.common.utils.LambdaUtils;
import com.jianguozh.difs.framework.base.BaseController;
import com.jianguozh.difs.framework.constant.SecurityConstant;
import com.jianguozh.difs.framework.security.AuthenticatedUser;
import com.jianguozh.difs.framework.utils.SecurityUtils;
import com.jianguozh.difs.framework.validator.group.AddGroup;
import com.jianguozh.difs.framework.validator.group.UpdateGroup;
import com.jianguozh.difs.support.api.ops.dto.OrgsDto;
import com.jianguozh.difs.support.api.ops.dto.UserDto;
import com.jianguozh.difs.support.api.ops.vo.UserDetailVo;
import com.jianguozh.difs.support.service.constant.enums.OrgEnum;
import com.jianguozh.difs.support.service.org.OrgServiceFactory;
import com.jianguozh.difs.support.service.org.entity.Org;
import com.jianguozh.difs.support.service.sys.entity.Res;
import com.jianguozh.difs.support.service.sys.entity.Role;
import com.jianguozh.difs.support.service.sys.entity.User;
import com.jianguozh.difs.support.service.sys.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户 前端控制器
 * </p>
 *
 * @author hanrs
 * @since 2022-03-17
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    @Autowired
    IUserService userService;

    /**
     * 由id获取对象
     */
    @GetMapping("/{id}")
    public R<User> get(@PathVariable String id) {
        return success(userService.getById(id));
    }

    /**
     * 由id获取对象详情
     */
    @GetMapping("/detail/{id}")
    public R<UserDetailVo> detail(@PathVariable String id) {
        UserDetailVo userDetailVo = new UserDetailVo();
        User entity = userService.getById(id);
        BeanUtil.copyProperties(entity, userDetailVo);
        List<Role> roles = userService.listUserRoles(id);
        userDetailVo.setRoles(roles);
        return success(userDetailVo);
    }

    /**
     * 新增
     */
    @PostMapping("")
    public R<User> add(@RequestBody @Validated(value = {AddGroup.class}) UserDto userDto) {
        User entity = new User();
        BeanUtil.copyProperties(userDto, entity);
        entity.setPassword(SecurityUtils.encryptPassword(entity.getPassword()));
        boolean result = userService.saveOrUpdateWithRole(entity, userDto.getRoleIds());
        return result ? success(entity) : failed("操作失败.");
    }

    /**
     * 修改
     */
    @PutMapping("")
    public R<User> modify(@RequestBody @Validated(value = {UpdateGroup.class}) UserDto userDto) {
        User entity = new User();
        BeanUtil.copyProperties(userDto, entity);
        boolean result = userService.saveOrUpdateWithRole(entity, userDto.getRoleIds());
        return result ? success(entity) : failed("操作失败.");
    }

    /**
     * 修改
     */
    @PutMapping("/info/{id}")
    public R<User> modifyBasic(@RequestBody @Validated(value = {UpdateGroup.class}) User user) {
        User entity = new User();
        BeanUtil.copyProperties(user, entity);
        boolean result = userService.saveOrUpdate(entity);
        return result ? success(entity) : failed("操作失败.");
    }

    /**
     * 批量删除
     */
    @DeleteMapping("/batch")
    public R<Boolean> deleteBatch(@RequestBody String[] ids) {
        boolean result = userService.removeByIds(Arrays.asList(ids));
        return result ? success(true) : failed("操作失败.");
    }

    /**
     * 单个删除
     */
    @DeleteMapping("/{id}")
    public R<Boolean> delete(@PathVariable String id) {
        boolean result = userService.removeById(id);
        return result ? success(true) : failed("操作失败.");
    }

    /**
     * 条件分页查询
     */
    @GetMapping("/page-query")
    public R<IPage<UserDetailVo>> pageQuery(HttpServletRequest request,
                                            @RequestParam(name = "name", required = false) String name,
                                            @RequestParam(name = "username", required = false) String username,
                                            @RequestParam(name = "orgId", required = false) String orgId,
                                            @RequestParam(name = "mobile", required = false) String mobile,
                                            @RequestParam(name = "status", required = false) Boolean status
    ) {

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();
        if (StrUtil.isNotBlank(name))
            lambdaQueryWrapper.like(User::getName, name);
        if (StrUtil.isNotBlank(username))
            lambdaQueryWrapper.like(User::getUsername, username);
        if (StrUtil.isNotBlank(orgId))
            lambdaQueryWrapper.eq(User::getOrgId, orgId);
        if (StrUtil.isNotBlank(mobile))
            lambdaQueryWrapper.like(User::getMobile, mobile);
        if (null != status)
            lambdaQueryWrapper.eq(User::getStatus, status);

        AuthenticatedUser authenticatedUser = SecurityUtils.getLoginUser();
        String org = authenticatedUser.getOrg();
        if (OrgEnum.CATERING.toString().equalsIgnoreCase(org) || OrgEnum.CORPORATE.toString().equalsIgnoreCase(org) || OrgEnum.SUPPLIER.toString().equalsIgnoreCase(org)) {
            String ownerOrgId = authenticatedUser.getOrgId();
            lambdaQueryWrapper.eq(User::getOrgId, ownerOrgId).ne(User::getOrgDefault, true);
        } else if (OrgEnum.SUPERIOR.toString().equalsIgnoreCase(org)) {
            lambdaQueryWrapper.eq(User::getOrg, OrgEnum.SUPERIOR.toString()).ne(User::getId, SecurityUtils.getSuperiorAdmin());
        } else { //不返回任何结果
            lambdaQueryWrapper.apply("1=2");
        }

        IPage<User> page = (IPage<User>) resolvePage(request);
        IPage<UserDetailVo> result = userService.page(page, lambdaQueryWrapper).convert(o -> {
            UserDetailVo vo = new UserDetailVo();
            BeanUtil.copyProperties(o, vo);
            vo.setRoles(userService.listUserRoles(o.getId()));
            return vo;
        });

        return success(result);
    }

    /**
     * 批量切换用户状态
     *
     * @param ids
     * @return
     */
    @PutMapping("/status")
    public R<Boolean> toggleStatus(@RequestBody String[] ids) {
        List<User> users = userService.listByIds(Arrays.asList(ids));
        users.forEach(user -> user.setStatus(!user.getStatus()));
        return success(userService.updateBatchById(users));
    }

    /**
     * 获取一个随机账号
     *
     * @return
     */
    @GetMapping("/username-random")
    public R<String> radomUsername() {
        Set<String> exists = userService.existUsername();
        Set<String> usernames = SecurityUtils.radomUsername(exists, 1);
        if (usernames.size() > 0) {
            return success(usernames.iterator().next());
        } else {
            return failed("获取随机账号失败.");
        }
    }

    /**
     * 批量创建默认管理员账号
     *
     * @param orgsDto
     * @return
     */
    @PreAuthorize("hasAnyAuthority('" + SecurityConstant.AUTHORITY_TAG_SUPERIOR + "')")
    @PostMapping("/manager")
    public R<Boolean> createDefaultManager(@RequestBody @Validated OrgsDto orgsDto) {
        List<String> noneManagerOrgNames = validDefaultManager(orgsDto);
        if (noneManagerOrgNames.size() > 0) {
            String msg = StrUtil.format("'{}'共{}个主体单位管理员姓名或手机号码为空,请检查后重试.", StrUtil.join("\n", noneManagerOrgNames), noneManagerOrgNames.size());
            return failed(msg);
        }

        //过滤已经存在的
        orgsDto.setOrgIds(orgsDto.getOrgIds().stream().filter(o -> {
            User manager = userService.getDefaultManager(o);
            return null == manager ? true : false;
        }).collect(Collectors.toList()));

        if (orgsDto.getOrgIds().size() > 0) {
            List<User> users = preCreateDefaultManager(orgsDto);
            return success(userService.saveBatch(users));
        } else {
            return failed("所选单位中均已存在默认管理员账号,无需设置.");
        }

    }

    /**
     * 当前用户
     *
     * @return
     */
    @GetMapping("/current")
    public R<AuthenticatedUser> current() {
        AuthenticatedUser authenticatedUser = SecurityUtils.getLoginUser();
        return success(authenticatedUser);
    }

    /**
     * 当前用户在登录client下的资源
     *
     * @return
     */
    @GetMapping("/res")
    public R<List<Tree<String>>> res() {
        AuthenticatedUser authenticatedUser = SecurityUtils.getLoginUser();
        String userId = authenticatedUser.getId();
        String clientId = authenticatedUser.getIssueClientId();
        List<Tree<String>> trees = userService.treeListUserClientRes(userId, clientId);
        return success(trees);
    }

    /**
     * 当前用户在登录client下授权的路由
     * @return
     */
    @GetMapping("/route")
    public R<List<String>> route(){
        AuthenticatedUser authenticatedUser = SecurityUtils.getLoginUser();
        String userId = authenticatedUser.getId();
        String clientId = authenticatedUser.getIssueClientId();
        List<Res> resList = userService.listUserClientRes(userId, clientId);
        List<String> route = resList.stream().map(Res::getPath).collect(Collectors.toList());
        return success(route);
    }

    /**
     * 校验组织默认管理员是否设置
     *
     * @param orgsDto
     * @return
     */
    private List<String> validDefaultManager(OrgsDto orgsDto) {
        OrgServiceFactory orgServiceFactory = new OrgServiceFactory(orgsDto.getOrg());
        List noneManagerOrgs = orgServiceFactory.listNoneManager(orgsDto.getOrgIds());
        return orgServiceFactory.listOrgName(noneManagerOrgs);
    }

    /**
     * 预生成默认管理员账号
     *
     * @param orgsDto
     * @return
     */
    private List<User> preCreateDefaultManager(OrgsDto orgsDto) {
        Set<String> exists = userService.existUsername();
        Set<String> usernameSet = SecurityUtils.radomUsername(exists, orgsDto.getOrgIds().size());
        String[] usernames = usernameSet.toArray(new String[usernameSet.size()]);

        List<User> users = new ArrayList<>();
        OrgServiceFactory orgServiceFactory = new OrgServiceFactory(orgsDto.getOrg());
        List<Org> orgs = orgServiceFactory.list(orgsDto.getOrgIds());
        orgs.forEach(LambdaUtils.consumerWithIndex((o, index) -> {
            User user = new User(orgsDto.getOrg(), o.getId(), true, o.getManager(), o.getManagerMobile(), true);
            user.setUsername(usernames[index]);
            user.setPassword(SecurityUtils.encryptPassword(o.getManagerMobile().substring(o.getManagerMobile().length() - 6) + "@Difs")); //手机号后6位作为密码
            users.add(user);
        }));
        return users;
    }

}
